package org.vectrics.client.framework;


import javax.swing.event.*;
import javax.swing.border.*;
import javax.swing.*;
import java.awt.event.*;
import java.awt.*;
import javax.swing.event.ListSelectionEvent;
import org.apache.log4j.*;
import org.vectrics.client.module.Module;
import org.vectrics.client.module.ModuleManager;
import org.vectrics.swing.GuiManager;
import java.util.Iterator;
import org.vectrics.client.webclient.*;



/**
* This class provides the frame for the main form for the LogLeap console.
* @author Mike Moore
* 
*/


// -----------------------------------------------------------------------------
// Layout of child components
// -----------------------------------------------------------------------------
//  ClientFrame
//		- ClientFrame.contentPane
//	      - MainSplitPanel
//  	        - LeftPanel          
//      	    - MainRightPane
//          	    - UserManageFrame
//          
// -----------------------------------------------------------------------------
public class ClientFrame extends JFrame implements 
		 ListSelectionListener, TreeSelectionListener, org.vectrics.client.webclient.ConnectionStatusListener {
	private static final long serialVersionUID = 7020321482340850243L;

    protected transient static Logger log = Logger.getLogger(ClientFrame.class);

    private ModuleManager moduleManager = null;
    private JList moduleList = null;   
    private JPanel contentPane;
    private JMenuBar menuBar = new JMenuBar();
    private JMenu jMenuFile = new JMenu();
    private JMenuItem jMenuFileExit = new JMenuItem();
    protected JLabel serverStatusLabel = null;    
    JMenu jMenuHelp = new JMenu();
    JMenuItem jMenuHelpAbout = new JMenuItem();
    
    JMenu menuModule = new JMenu();
    
    JPanel modulePanel = new JPanel();
    //JScrollPane moduleNavigatePane = new JScrollPane();
    JPanel moduleNavigatePanel = new JPanel();
    ImageIcon image1;
    ImageIcon image2;
    ImageIcon image3;
    DefaultListModel serverListModel = new DefaultListModel();
    Border border1;
    Box box2;

    JSplitPane mainSplitPane = new JSplitPane();

	JPanel leftPanel = new JPanel();
	
    JMenu menuOptions = new JMenu();
    JMenuItem addServerMenuItem = new JMenuItem();
    JMenuItem editServerMenuItem = new JMenuItem();
    JMenuItem removeServerMenuItem = new JMenuItem();
    JMenuItem connectServerMenuItem = new JMenuItem();
    
    JMenuItem clearMessageListMenuItem = new JMenuItem();

    JPanel nodeLevelPanel = new JPanel();
    JScrollPane userScrollPane = new JScrollPane();

    
    
    private static int FRAME_HEIGHT = 600;
    private static int FRAME_WIDTH = 600;

    /**
    * Constructor 
    */
      public ClientFrame(ClientConfiguration config) {
      	super();
        log.debug("ClientFrame constructor called");
		this.setTitle(config.getApplicationName());
		CommandDispatcher.getInstance().setConnectionStatusListener(this);        
        enableEvents(AWTEvent.WINDOW_EVENT_MASK);
        try {
            log.info("creating default server connection");
            
            
            log.info("initializing GUI");
			modulePanel.setBackground(Color.BLUE);
			moduleManager = new ModuleManager(modulePanel, moduleNavigatePanel);
			moduleManager.setModules(config.getModules());
			
            initComponents();
			
            this.pack();
			log.info("done intializing GUI - setting up connections");

            initRefreshTimer();
            
        }
        catch(Exception e) {
            log.error("ClientFrame constructor encountered an exception", e);
        }
        
        ImageIcon icon = new ImageIcon("app.gif", "Application Icon");
        
        this.setIconImage(icon.getImage());
  }


   
      
    
  /**
   * Component initialization
   */
  private void initComponents() throws Exception  {
        log.debug("initComponents() called");

        
        contentPane = (JPanel) this.getContentPane();

        border1 = BorderFactory.createBevelBorder(BevelBorder.RAISED,
                Color.white, Color.white,
                new Color(148, 145, 140), new Color(103, 101, 98));
        box2 = Box.createHorizontalBox();


        image1 = new ImageIcon("graphics/openFile.gif");
        image2 = new ImageIcon("graphics/closeFile.gif");
        image3 = new ImageIcon("graphics/help.gif");

        this.setSize(new Dimension(835, 613));
        
        initMenu();


        log.info("initComponents() - setting up content panel");
        contentPane.setBackground(GuiManager.getInstance().getBackgroundColor());
        contentPane.setFont(new java.awt.Font("Dialog", 0, 10));
        contentPane.setMinimumSize(new Dimension(FRAME_WIDTH, FRAME_HEIGHT));
        contentPane.setPreferredSize(new Dimension(FRAME_WIDTH + 100, FRAME_HEIGHT + 100));
        //contentPane.setLayout(new BoxLayout(contentPane, BoxLayout.Y_AXIS));
		contentPane.add(mainSplitPane);

        initLeftPanel();

		mainSplitPane.setOrientation(JSplitPane.HORIZONTAL_SPLIT);
        mainSplitPane.add(leftPanel, JSplitPane.LEFT);
        mainSplitPane.add(this.modulePanel, JSplitPane.RIGHT);
    }

  
  	private void showConnectionStatus() {
  		
  	}
  	
  	class StatusUpdateRunnable implements Runnable {
  		public ConnectionStatus theStatus = null;
  		public void run() {
  			serverStatusLabel.setText(theStatus.getDescription());
  		}
  	}
  	
  	public void statusUpdate(ConnectionStatus status) {
  		log.debug("received connection status update");
  		StatusUpdateRunnable doWorkRunnable = new StatusUpdateRunnable();
  		doWorkRunnable.theStatus = status;
  		SwingUtilities.invokeLater(doWorkRunnable);
  		
  	}
  	
	private void initMenu() {
		Font menuFont = GuiManager.getInstance().getStandardFont();
		
		jMenuFile.setFont(menuFont);
		jMenuFile.setText("File");
		jMenuFileExit.setFont(menuFont);
		jMenuFileExit.setText("Exit");
	
		jMenuFileExit.addActionListener(new ActionListener()  {
			public void actionPerformed(ActionEvent e) {
				jMenuFileExit_actionPerformed(e);    }
			});
	
		jMenuHelp.setFont(menuFont);
		jMenuHelp.setText("Help");
		jMenuHelpAbout.setFont(menuFont);
		jMenuHelpAbout.setText("About");
	
		
		menuModule.setFont(menuFont);
		menuModule.setText("Modules");
			
		log.info("initComponents() - setting up menus");
		menuOptions.setFont(menuFont);
		menuOptions.setText("Options");


		addServerMenuItem.setFont(menuFont);
		addServerMenuItem.setText("Add Server");

            
		editServerMenuItem.setFont(menuFont);
		editServerMenuItem.setText("Change Selected Server");
		editServerMenuItem.setEnabled(false);

		removeServerMenuItem.setFont(menuFont);
		removeServerMenuItem.setText("Remove Selected Server");
		removeServerMenuItem.setEnabled(false);

		connectServerMenuItem.setFont(menuFont);
		connectServerMenuItem.setText("Connect");
		connectServerMenuItem.setEnabled(false);
            
		menuBar.setFont(menuFont);
		clearMessageListMenuItem.setFont(menuFont);
		clearMessageListMenuItem.setText("Clear Messages");

			
		jMenuFile.add(jMenuFileExit);
		jMenuHelp.add(jMenuHelpAbout);

		menuBar.add(jMenuFile);
		menuBar.add(menuOptions);
		menuBar.add(jMenuHelp);
		menuBar.add(menuModule);
		
		this.setJMenuBar(menuBar);

		menuOptions.add(addServerMenuItem);
		menuOptions.add(connectServerMenuItem);
		menuOptions.add(editServerMenuItem);
		menuOptions.add(removeServerMenuItem);
		menuOptions.add(clearMessageListMenuItem);
	}


    private void initRefreshTimer() {
		log.info("Refresh timer initializing...");
    }
    
    
    private JComponent createModuleSelectPanel() {
    	moduleList = new JList();
    	moduleList.setFont(GuiManager.getInstance().getStandardFont());
    	
    	DefaultListModel model = new DefaultListModel();
    	moduleList.addListSelectionListener(this);
    	moduleList.setModel(model);
    	modulePanel.add(moduleList);
    	
    	
    	Iterator iter = ModuleManager.getInstance().getModuleList().iterator();
    	while (iter.hasNext()) {
    		Module module = (Module)iter.next();
			log.info("Adding next module: " + module.getName());
			model.addElement(module);
			JMenuItem menuItem = new JMenuItem();
			menuItem.setText(module.getName());
			menuItem.setFont(GuiManager.getInstance().getStandardFont());
			
			menuItem.addActionListener(new ActionListener()  {
				public void actionPerformed(ActionEvent e) {
					moduleMenuItemClicked(e);    }
			});
			
			this.menuModule.add(menuItem);
			
    	}
    	
    	
    	return(moduleList);
    }

    public void moduleMenuItemClicked(ActionEvent e) {
    	if (e.getSource() instanceof JMenuItem) {
    		JMenuItem clickedMenuItem = (JMenuItem)e.getSource();
    		log.info("Module menu item clicked, finding associated module...");
    		
    		Iterator iter = ModuleManager.getInstance().getModuleList().iterator();
    		Module desiredModule = null;
    		while ((iter.hasNext()) && (desiredModule == null)) {
    			Module module = (Module)iter.next();
    			log.info("Adding next module: " + module.getName());
    			if (module.getName().equals(clickedMenuItem.getText())) {
    				desiredModule = module;
    			}
    		}
    		if (desiredModule == null) {
    			log.error("Could not find module with name = " + clickedMenuItem.getText());
    		}
    		else {
    			log.debug("Found module, showing module...");
    			try {
    				ModuleManager.getInstance().showModule(desiredModule);
    			}
    			catch (Exception ve) {
    				log.error("Error showing module: " + desiredModule.getName(), ve);
    				ErrorFrame.showError(this, "Error Showing Module", "Error showing module: " + desiredModule.getName(), ve.getMessage());
    			}
    		}
    		
    	}
	}

    private void initLeftPanel() {
        log.info("initLeftPanel() - setting up category tree and node controls");

        leftPanel.setBackground(Color.blue);
        leftPanel.setLayout(new BoxLayout(leftPanel, BoxLayout.Y_AXIS));
        leftPanel.setMinimumSize(new Dimension(100, 100));
        
		JSplitPane leftSplitPane = new JSplitPane();
		leftPanel.add(leftSplitPane);
		
		JPanel moduleHolderPanel = new JPanel();
		moduleHolderPanel.setLayout(new BorderLayout());
		JPanel moduleCaptionPanel = new JPanel();
		moduleCaptionPanel.setMaximumSize(new Dimension(1000, 15));
		moduleCaptionPanel.setMaximumSize(new Dimension(5, 15));
		moduleCaptionPanel.setLayout(new BorderLayout());
		moduleCaptionPanel.setBorder(GuiManager.getInstance().getEtchedBorder()); 
		
		JLabel moduleLabel = new JLabel();
		moduleLabel.setText("Modules");
		moduleLabel.setFont(GuiManager.getInstance().getStandardFont());
		moduleLabel.setHorizontalAlignment(SwingConstants.CENTER);
		moduleCaptionPanel.add(moduleLabel);
		moduleHolderPanel.add(moduleCaptionPanel, BorderLayout.NORTH);
		
		JScrollPane moduleSelectPane = new JScrollPane();
		moduleSelectPane.setBackground(Color.BLUE);
		moduleHolderPanel.add(moduleSelectPane, BorderLayout.CENTER);
		
		//JPanel moduleSelectPanel = createModuleSelectPanel();
		//moduleSelectPanel.setBackground(Color.YELLOW);
		moduleSelectPane.getViewport().add(createModuleSelectPanel());
		
		JPanel bottomPanel = new JPanel();
		bottomPanel.setLayout(new BorderLayout());
		moduleNavigatePanel.setBorder(GuiManager.getInstance().getEtchedBorder());
		bottomPanel.add(moduleNavigatePanel, BorderLayout.CENTER);
		
		JPanel serverPanel = new JPanel();
		serverPanel.setMinimumSize(new Dimension(10, 80));
		leftPanel.setMaximumSize(new Dimension(4100, 80));
		serverPanel.setBorder(GuiManager.getInstance().getEtchedBorder());
		serverStatusLabel = new JLabel();
		serverStatusLabel.setText("Server Status");
		serverStatusLabel.setHorizontalAlignment(SwingConstants.CENTER);
		serverStatusLabel.setFont(GuiManager.getInstance().getStandardFont());
		
		serverPanel.add(serverStatusLabel);
		
		bottomPanel.add(serverPanel, BorderLayout.PAGE_END);

		JPanel leftLowerPanel = new JPanel();
		leftSplitPane.setOrientation(JSplitPane.VERTICAL_SPLIT);
		leftSplitPane.add(moduleHolderPanel, JSplitPane.TOP);
		leftSplitPane.add(bottomPanel, JSplitPane.BOTTOM);
    }
  

   

  /**
   * Refresh all controls with the current states of the programming elements
   * they represent.
  */
    public void refresh()
    {
        
        log.debug("refresh() - syncronize finish");

        log.debug("refresh() - done");
    };


    

    private void prepareMenu() {
        
    }

    
  /**
   * This method receives notification when a node is selected on the logger tree.
   * @param event    The event that represents the change.
  */
    public synchronized void valueChanged(TreeSelectionEvent event) {
        
        log.debug("valueChanged() - new tree selection called");
        prepareMenu();
        log.debug("valueChanged(TreeSelectionEvent) - done");
    }


    /**
     * Enable the menu options that require a server node to be selected.
     */
    private void enableServerMenuOptions() {
        log.debug("enableServerMenuOptions() called");
        this.removeServerMenuItem.setEnabled(true);
        this.editServerMenuItem.setEnabled(true);
        this.connectServerMenuItem.setEnabled(true);
    }
    
    /**
     * Disable the menu options that require a server node to be selected.
     */
    private void disableServerMenuOptions() {
        log.debug("disableServerMenuOptions() called");
        this.removeServerMenuItem.setEnabled(false);
        this.editServerMenuItem.setEnabled(false);
        this.connectServerMenuItem.setEnabled(false);
    }
    

  /**
   * Detect user selection changes with Message table.
  */
    public void valueChanged(ListSelectionEvent event)
    {
    	log.info("valueChanged() - called, source class = " + event.getSource().getClass().getName());
    	if (event.getSource() == moduleList) {
    		int selectedIndex = moduleList.getSelectedIndex();
			log.info("New module selected, index = " + selectedIndex);
			DefaultListModel selModel = (DefaultListModel)moduleList.getModel();
			if (selectedIndex >= 0) {
				Module module = (Module)selModel.getElementAt(selectedIndex);
				try {
					moduleManager.showModule(module);
				}
				catch (Exception ve) {
					log.error("Error showing module: " + module.getName(), ve);
					ErrorFrame.showError(this, "Error Showing Module", "Error showing module: " + module.getName(), ve.getMessage());
				}
				
			}
			
    	}

    };
    


    public void treeStructureChanged(TreeModelEvent iEvent)
    {
    }

    public void treeNodesRemoved(TreeModelEvent iEvent)
    {
    }

    public void treeNodesInserted(TreeModelEvent iEvent)
    {
    }

    public void treeNodesChanged(TreeModelEvent iEvent)
    {
    }

    /**File | Exit action performed*/
    public void jMenuFileExit_actionPerformed(ActionEvent e) {
        System.exit(0);
    }

    /**Overridden so we can exit when window is closed*/
    protected void processWindowEvent(WindowEvent e) {
        //log.debug("processWindowEvent() - method to monitor low level windows events");
        super.processWindowEvent(e);
        if (e.getID() == WindowEvent.WINDOW_CLOSING) {
            jMenuFileExit_actionPerformed(null);
        }
    }



    
    
    
    

    
   
    
}